﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Medianamik.Core;
using System.Net;
using System.IO;
using System.Threading;
using Medianamik.Core.Logging;
using NLog;
using Medianamik.Globalization;
using Medianamik.UI.Mediasend.NodeTypes;

namespace Medianamik.UI.Mediasend.Logic
{
    /// <summary>
    /// Conteneur des données nécessaires à l'envoi d'une mailing list
    /// </summary>
    [Serializable]
    public class MailingDataShell
    {
        #region " MEMBERS "
            private Guid? _targetTemplateId;
            public string Content;
            private string _mailingName;
            private string _senderEmail;
            private string _senderName;
            private string _subject;
            private int? _campaingId;
            private int? _listId;
            private int? _subListId;
            private string _culture;
            
            public bool AlreadyBeenSaved;
            protected bool Saved;
            protected bool IsDirty;
            protected int MailingId;

            [NonSerialized]
            private MediasendTemplate _targetTemplate;
            /// <summary>
            /// Template qui contient le contenu du courriel.
            /// </summary>
            public MediasendTemplate TargetTemplate
            {
                get
                {
                    if (_targetTemplate == null && TargetTemplateId != null)
                        _targetTemplate = NodeManager.GetNode<MediasendTemplate>(TargetTemplateId.Value);

                    return _targetTemplate;
                }
            }

            public Guid? TargetTemplateId
            {
                get { return _targetTemplateId; }
                set 
                {
                    IsDirty = true;
                    _targetTemplate = null;
                    _targetTemplateId = value; 
                }
            }

            public int? CampaingId
            {
                get { return _campaingId; }
                set
                {
                    IsDirty = true;
                    _campaingId = value;
                }
            }

            public string MailingName
            {
                get { return _mailingName; }
                set
                {
                    IsDirty = true;
                    _mailingName = value;
                }
            }

            public string SenderEmail
            {
                get { return _senderEmail; }
                set
                {
                    IsDirty = true;
                    _senderEmail = value;
                }
            }

            public string SenderName
            {
                get { return _senderName; }
                set
                {
                    IsDirty = true;
                    _senderName = value;
                }
            }

            public string Subject
            {
                get { return _subject; }
                set
                {
                    IsDirty = true;
                    _subject = value;
                }
            }

            public int? ListId
            {
                get { return _listId; }
                set
                {
                    IsDirty = true;
                    _listId = value;
                }
            }

            public int? SubListId
            {
                get { return _subListId; }
                set
                {
                    IsDirty = true;
                    _subListId = value;
                }
            }

            public string Culture
            {
                get { return _culture; }
                set
                {
                    IsDirty = true;
                    _culture = value;
                }
            }
        #endregion

        #region " EVENTS "

            public delegate void Sent();

            [NonSerialized]    
            private Sent _sentEvent;
            
            public event Sent OnSent
            {
                add { _sentEvent += value; }
                remove { _sentEvent -= value; }
            }

        #endregion

        /// <summary>
        /// Valider si l'ensemble des valeurs saisies sont valides.
        /// </summary>
        /// <returns></returns>
        public bool IsValid(out string Error)
        {
            Error = "";

            if ((Content ?? "").Trim() != "")
                return true;
            else
            {
                Error = Translator.Translate("Medianamik_Mediasend", "ErrorContentEmpty");
                return false;
            }
        }

        
        /// <summary>
        /// Création du Mailing dans Mediasend.
        /// </summary>
        public bool Save()
        {
            if (!Saved)
            {
                var session = MediasendManager.Instance.OpenSession(Configuration.Instance.Properties.Username,
                                                                    Configuration.Instance.Properties.Password);

                var mailing = session.CreateMailing(CampaingId.Value, MailingName);

                if (SaveMailing(mailing, session))
                {
                    Saved = true;
                    IsDirty = false;
                    AlreadyBeenSaved = true;
                    return true;
                }

                return false;
            }
            else if (IsDirty && MailingId > 0)
            {
                var session = MediasendManager.Instance.OpenSession(Configuration.Instance.Properties.Username,
                                                                    Configuration.Instance.Properties.Password);

                var mailing = session.GetMailing(MailingId);

                mailing.Name = MailingName;

                if (SaveMailing(mailing, session))
                {
                    Saved = true;
                    IsDirty = false;
                    AlreadyBeenSaved = true;
                    return true;
                }

                return false;
            }

            return true;
        }

        /// <summary>
        /// Sauvegarde interne du mailing
        /// </summary>
        /// <param name="mailing"></param>
        private bool SaveMailing(MediasendMailing mailing, MediasendSession session)
        {
            ParseContent();
            if (Content != "")
            {
                mailing.SenderEmail = SenderEmail;
                mailing.SenderName = SenderName;
                mailing.Subject = Subject;
                mailing.Message = Content;
                mailing.ListId = ListId;
                mailing.SubListId = SubListId;
                mailing.Save();

                MailingId = mailing.ID;

                return true;
            }

            return false;
        }

        /// <summary>
        /// Nous permet de resauvegarder le Mailing peut importe s'il a déjà été sauvegardé.
        /// </summary>
        public void ForceSaveNew()
        {
            Saved = false;
            Save();
        }

        /// <summary>
        /// Forcer une mise à jour du Mailing
        /// </summary>
        public void ForceUpdate()
        {
            IsDirty = true;
            Save();
        }

        /// <summary>
        /// Envoi du courriel Test de conformité.
        /// </summary>
        /// <param name="email"></param>
        public bool SendTest(string email)
        {
            
            try
            {
                var session = MediasendManager.Instance.OpenSession(Configuration.Instance.Properties.Username,
                                                                    Configuration.Instance.Properties.Password);

                session.GetMailing(MailingId).SendTest(email);
                return true;
            }
            catch (Exception exc)
            {
                var logger = LogManager.GetLogger("ActivityLogger");
                if (MediasendManager.Instance.LastError != "")
                    logger.ErrorException("Error while sending test email : " + MediasendManager.Instance.LastError, exc);
                else
                    logger.ErrorException("Error while sending test email", exc);

                return false;
            }
            
        }

        /// <summary>
        /// Envoi défénitive du newsletter.
        /// </summary>
        public bool SendNewsletter()
        {
            try
            {
                var session = MediasendManager.Instance.OpenSession(Configuration.Instance.Properties.Username,
                                                                    Configuration.Instance.Properties.Password);

                session.GetMailing(MailingId).Send();

                if (_sentEvent != null)
                    _sentEvent();

                return true;
            }
            catch (Exception exc)
            {
                var logger = LogManager.GetLogger("ActivityLogger");
                if (MediasendManager.Instance.LastError != "")
                    logger.ErrorException("Error while sending newsletter : " + MediasendManager.Instance.LastError, exc);
                else
                    logger.ErrorException("Error while sending newsletter", exc);

                return false;
            }
        }

        /// <summary>
        /// Extracton du contenu du gabarit de courriel ciblé.
        /// </summary>
        public void ParseContent()
        {
            try
            {
                var url = DefaultUrl();
                if (!url.StartsWith("http"))
                    url = GetLeftPartUrl()+url;

                var response = WebRequest.Create(url).GetResponse();
                var streamReader = new StreamReader(response.GetResponseStream());

                Content = streamReader.ReadToEnd();

                var parser = new StyleParser(TargetTemplate.StyleContent);
                Content = parser.Parse(Content);            

                streamReader.Close();
                response.Close();
            }
            catch (Exception e)
            {
                Content = "";
                LogManager.GetLogger("ActivityLogger").ErrorException("Error while parsing newsletter content", e);
            }

        }

        /// <summary>
        /// Extraction de l'url du Gabarit
        /// </summary>
        /// <returns></returns>
        private string DefaultUrl()
        {
            return new Client.Utility()
                        .GetDefaultRelativePath(TargetTemplateId.Value,
                                                System.Globalization.CultureInfo.GetCultureInfo(Culture));
            
        }

        /// <summary>
        /// Retourne la première partie de l'URL (http://domaine:port)
        /// </summary>
        /// <returns></returns>
        private string GetLeftPartUrl()
        {
            return HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Host + ":" +
                   HttpContext.Current.Request.Url.Port;
        }
    }
}
